<?php
require './function.php';
/**
 * @Author: Wherein
 * @Date: 2021-04-16 14:55
 * @Descripttion: 
 */

// 抽象处理者
abstract class Handler
{
    private $next_handler; // 存放下一处理对象
    private $level = 0; // 处理级别默认为0

    abstract protected function response(); // 处理者回应

    // 设置处理级别
    public function setHandlerLevel($level)
    {
        $this->level = $level;
    }
    // 设置下一个处理者是谁
    public function setNext(Handler $handler)
    {
        $this->next_handler = $handler;
        $this->next_handler->setHandlerLevel($this->level + 1);
    }

    // 责任链实现主要方法，判断 责任是否属于该对象，不属于则转发给下一级。 使用final不允许重写
    final public function handlerMessage(Request $request)
    {
        if ($this->level == $request->getLevel()) {
            $this->response();
        } else {
            if ($this->next_handler != null) {
                $this->next_handler->handlerMessage($request);
            } else {
                dd('洗洗睡吧，没人理你了');
            }
        }
    }
}

// 具体处理者
// headman 组长
class HeadMan extends Handler
{
    protected function response()
    {
        dd('组长回复你：同意你的请求');
    }
}

// 主管director
class Director extends Handler
{
    protected function response()
    {
        dd('主管回复你：知道了，退下吧');
    }
}

// 经理manager
class Manager extends Handler
{
    protected function response()
    {
        dd('经理回复你：容朕思虑；再议吧');
    }
}

// 请求类
class Request
{
    protected $level = array('请假' => 0, '休假' => 1, '离职' => 2);
    protected $request;
    public function __construct($request)
    {
        $this->request = $request;
    }

    public function getLevel(){
        // 获取请求对应的级别，如果该 请求没有对应级别 返回-1
        return array_key_exists($this->request, $this->level) ? $this->level[$this->request] : -1;
    }
}

// 实例化处理者
$headman = new HeadMan;
$director = new Director;
$manager = new Manager;
// 责任链组装
$headman->setNext($director);
$director->setNext($manager);
// 传递请求
$headman->handlerMessage(new Request('请假'));
$headman->handlerMessage(new Request('休假'));
$headman->handlerMessage(new Request('不干了'));
$headman->handlerMessage(new Request('离职'));
